//
//  ViewController.swift
//  videoCapture
//
//  Created by yeqingyu on 16/11/5.
//  Copyright © 2016年 yeqingyu. All rights reserved.
//

import UIKit
import AVFoundation

private let menuHeight:CGFloat = 49.0
private let btnWidth:CGFloat = 100
private let menuMarginX:CGFloat = 20
private let screenWidth:CGFloat = UIScreen.main.bounds.size.width
class ViewController: UIViewController {
    // MARK:- 视频输入源的全局队列
    fileprivate lazy var videoOutPutQueue = DispatchQueue.global()
    // MARK:- 声音输入源的全局队列
    fileprivate lazy var audioOutPutQueue = DispatchQueue.global()
    // MARK:-1.创建捕捉会话
    fileprivate lazy var session:AVCaptureSession = AVCaptureSession()
    // MARK:- 创建预览图层
    fileprivate lazy var previewLayer:AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.session)
    
    fileprivate  var videoOutPut : AVCaptureVideoDataOutput?
    
    fileprivate var videoInput:AVCaptureDeviceInput?
    
    fileprivate var movieFileOutput:AVCaptureFileOutput?
    
    fileprivate lazy var menuView:UIView = {
        let rect = CGRect(x: 0, y: 0, width: screenWidth, height: menuHeight)
        let menuView = UIView(frame: rect)
        menuView.backgroundColor = UIColor.black
        menuView.alpha = 0.3
        //1.床架开始录制按钮
        let starCapBtnRect = CGRect(x: menuMarginX, y: 0, width: btnWidth, height: menuHeight)
        let starCapBtn = UIButton(frame: starCapBtnRect)
        starCapBtn.setTitle("开始录制", for: .normal)
        starCapBtn.addTarget(self, action: #selector(ViewController.starCapture), for: UIControlEvents.touchUpInside)
        //2.创建结束录制按钮
        let stopCapBtn = UIButton()
        stopCapBtn.frame.size = CGSize(width: btnWidth, height: menuHeight)
        stopCapBtn.center = menuView.center
        stopCapBtn.setTitle("结束录制", for: .normal)
        stopCapBtn.addTarget(self, action: #selector(ViewController.stopCapture), for: UIControlEvents.touchUpInside)
        
        //3.切换镜头按钮
        let changeCapBtnRect = CGRect(x: screenWidth-menuMarginX-btnWidth, y: 0, width: btnWidth, height: menuHeight)
        let changeCapBtn = UIButton(frame: changeCapBtnRect)
        changeCapBtn.setTitle("切换镜头", for: .normal)
        changeCapBtn.addTarget(self, action: #selector(ViewController.changeCapture), for: UIControlEvents.touchUpInside)
        
        menuView.addSubview(starCapBtn)
        menuView.addSubview(stopCapBtn)
        menuView.addSubview(changeCapBtn)
        return menuView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
         setUpTopMenuView()
    }

}
extension ViewController{
    func setUpTopMenuView(){
        //添加头部菜单视图
        view.addSubview(menuView)
    }
    
    // MARK:- 开始录制视频
    func starCapture(){
        print("开始录制")
        
        //1.设置视频的输入源和输出源
        setUpVideoInputAndOutPut()
        
        //2.设置音频的输入源和输出源
        setUpAudioInputAndOutPut()
        
        //3.给用户设置一个预览图层
        previewLayer.frame = view.bounds
        view.layer.insertSublayer(previewLayer, at: 0)
      
        //4.创建文件写入输出
        let movieFileOutput = AVCaptureMovieFileOutput()
        session.addOutput(movieFileOutput)
        self.movieFileOutput = movieFileOutput
     
        //4.1设置文件的写入稳定性
        guard let movieConnection = movieFileOutput.connection(withMediaType: AVMediaTypeVideo) else {return}
        movieConnection.preferredVideoStabilizationMode = .auto
        
        //5.开始捕捉
        session .startRunning()
        
        //6.开始采集数据,写入到沙盒路径
        guard let cacheStr = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first else { print("获取沙盒路径失败");return }
        let url = URL(fileURLWithPath: cacheStr + "movie.mp4")
        movieFileOutput.startRecording(toOutputFileURL: url, recordingDelegate: self)
    }
    
    // MARK:- 结束录制视频
    func stopCapture(){
        print("结束录制")
        //1.结束文件写入
        movieFileOutput?.stopRecording()
        //2.结束会话
        session .stopRunning()
        //3.移除预览图层
        previewLayer.removeFromSuperlayer()
    }
    
    // MARK:- 切换镜头
    func changeCapture(){
        print("切换镜头")
        //1.获取之前的镜头
        guard  var position = videoInput?.device.position else {return}
        
        position = position == .front ? .back :.front
        guard  let divices =  AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else{
            print("获取设备失败")
            return
        }
        //2.创建当前新的输入源设备
        guard let divice = divices.filter({$0.position == position}).first else {return}
       //3.根据当前的设备创建新的输入源
        guard let videoInput = try?AVCaptureDeviceInput(device: divice) else{return}
        
        //4.添加到会话中
        session.beginConfiguration()
        session.removeInput(self.videoInput)
        session.addInput(videoInput)
        session.commitConfiguration()
        self.videoInput = videoInput
        
    }
}


extension ViewController{
    // MARK:- 设置视频的输入源/输出源
    fileprivate func setUpVideoInputAndOutPut(){
    //2.给会话设置输入源(摄像头)
    guard  let divices =  AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else{
    print("获取设备失败")
    return
    }
    print(divices)
    guard let divice = divices.filter({$0.position == .front}).first else {return}
    guard let videoInput = try?AVCaptureDeviceInput(device: divice) else{return}
    self.videoInput = videoInput
    session.addInput(videoInput)
        
    let videoOutput = AVCaptureVideoDataOutput()
    videoOutput.setSampleBufferDelegate(self, queue: videoOutPutQueue)
    session.addOutput(videoOutput)
    self.videoOutPut = videoOutput
        
        
    }
   
    // MARK:- 设置音频的输入源
    fileprivate func setUpAudioInputAndOutPut(){
        //2.给会话设置输入源(摄像头)
        guard  let divice =  AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio) else{
            print("获取设备失败")
            return
        }
        print(divice)
        guard let audioInput = try?AVCaptureDeviceInput(device: divice) else{return}
        session.addInput(audioInput)
        
        let audioOutput = AVCaptureAudioDataOutput()
        audioOutput.setSampleBufferDelegate(self, queue: audioOutPutQueue)
        session.addOutput(audioOutput)
    }

}

// MARK:- 音视频数据输出代理
extension ViewController :AVCaptureVideoDataOutputSampleBufferDelegate,AVCaptureAudioDataOutputSampleBufferDelegate{
    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
        print("输出数据")
        
        if connection == self.videoOutPut?.connection(withMediaType: AVMediaTypeVideo){
           print("捕捉到视频数据")
        }else{
           print("捕捉到音频数据")
        }
    }
}

// MARK:- 写入文件代理
extension ViewController : AVCaptureFileOutputRecordingDelegate{

    func capture(_ captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAt fileURL: URL!, fromConnections connections: [Any]!) {
        print("开始写入文件")
    }
    
    
    func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) {
        print("写入完成")
    }
}
